import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get_rx/get_rx.dart';
import 'package:share_fit/app/components/keep_alive_wrapper.dart';
import 'package:share_fit/app/controllers/base/base_controller.dart';
import 'package:share_fit/app/controllers/device/device_view.dart';
import 'package:share_fit/app/controllers/home/home_view.dart';
import 'package:share_fit/app/controllers/space/space_view.dart';
import 'package:share_fit/app/controllers/sports/sports_view.dart';
import 'package:share_fit/app/network/net_const.dart';
import 'package:share_fit/app/tools/app_const.dart';
import 'package:share_fit/app/tools/app_util.dart';
import 'package:share_fit/app/tools/date_tool.dart';
import 'package:share_fit/app/ute/uteped_bind.dart';
import 'package:share_fit/app/ute/uteped_const.dart';
import 'package:sqflite/sqflite.dart';

import 'main_state.dart';

class MainLogic extends BaseController {
  static String HTTP_BASE = 'https://watchapp.wiodo.tech';
  String uploadSignURL = '$HTTP_BASE/api/v2/upload-sign?type=0';
  String downloadSignURL = '$HTTP_BASE/api/v2/download-sign';
  String deleteURL = '$HTTP_BASE/api/v2/storage/';

  final String dbName = 'uteped_db.db'; /// 手机上已存在，要上传的db文件名称
  final String fileName = 'uteped_db.dat'; ///上传/删除时候保存的文件名称
  final String downloadFileName = 'uteped_db.db'; ///下载到手机上时保存的文件名称
  final String keyUploadFileTime = 'upload_file_time';
  final MainState state = MainState();

  late PageController pageController;
  var selectPage = 0.obs;

  late Animation<double> opacityAnim;

  List<KeepAliveWrapper> pages = [
    // HomePage(key: const ValueKey(AppConst.homePage)),
    // // SportsPage(key: const ValueKey(AppConst.sportsPage)),
    // DevicePage(key: const ValueKey(AppConst.devicePage)),
    // SpacePage(key: const ValueKey(AppConst.spacePage))

    KeepAliveWrapper(child: HomePage(key: const ValueKey(AppConst.homePage))),
    KeepAliveWrapper(child: SportsPage(key: const ValueKey(AppConst.sportsPage))),
    KeepAliveWrapper(child: DevicePage(key: const ValueKey(AppConst.devicePage))),
    KeepAliveWrapper(child: SpacePage(key: const ValueKey(AppConst.spacePage))),
  ];

  @override
  void onInit() {
    super.onInit();
    pageController = PageController(initialPage: 0);
    opacityAnim= Tween<double>(begin: 0.2,end: 1.0).animate(animCtrl);
    save(AppConst.tabPage, 0, global: true);
  }

  void goToTab(int page) {
    selectPage.value = page;
    // animCtrl.forward();
    // pageController.animateToPage(page, duration: const Duration(milliseconds: 400), curve: Curves.ease);
    pageController.jumpToPage(page);
    ValueKey<String>  pageKey = currentPage().key as ValueKey<String>;
    save(AppConst.tabPage, pageKey.value, global: true);
  }

  Widget currentPage() {
    return pages[selectPage.value].child;
  }

  @override
  void dispose() {
    pageController.dispose();
    super.dispose();
  }

  @override
  String getRemotePath() {
    return UTEPedConst.pathDevice;
  }

  @override
  void initState() {
    // TODO: implement initState
  }

  @override
  void onRemoteEvent(event, method) {
    // TODO: implement onRemoteEvent
  }

  Future<dynamic> downloadSign() async {
    String sn = read(UTEPedConst.keyAddress, global: true).replaceAll(':', '');
    String userId = read('login_id', global: true);
    if(sn.isEmpty||userId.isEmpty) {
      return;
    }
    final dio = Dio();
    dio.options.headers.addAll({'token':read(NetConst.keyUserToken, global: true)});
    dio.interceptors.add(LogInterceptor(requestBody: true, responseBody: true));
    String objectKey = 'watch/$userId/$sn/$fileName';
    Map<String, dynamic> params = {'type':0, 'objectKey':objectKey, 'sn':sn};
    try {
      Response response = await dio.get(downloadSignURL, queryParameters: params);
      Map map = jsonDecode(jsonEncode(response.data));
      if(map['code']==200) {
        Map dataMap = map['data'];
        String scheme = dataMap['scheme'];
        String netloc = dataMap['netloc'];
        String path = dataMap['path'];
        String query = dataMap['query'];

        String downloadPath = '$scheme://$netloc$path?$query';
        _downloadFile(downloadPath);
      }
      return response;
    } catch(e){
      if(e is DioException) {
        return e.response;
      } else {
        return e.toString();
      }
    }
  }

  Future<dynamic> _downloadFile(String path) async {
    String localPath = await getDatabasesPath();

    final dio = Dio();
    dio.interceptors.add(LogInterceptor(requestBody: true, responseBody: true));

    try{
      Response response = await dio.download(path, '$localPath/$downloadFileName',
          onReceiveProgress: (progress, total) {
            print('downloadFile progress:$progress|total:$total');
          });
      return response;
    }catch(e) {
      return e.toString();
    }
  }

  Future<dynamic> uploadSign() async {
    String sn = read(UTEPedConst.keyAddress, global: true).replaceAll(':', '');
    String userId = read('login_id', global: true);
    if(sn.isEmpty||userId.isEmpty) {
      return;
    }

    int uploadFileTime = read(keyUploadFileTime, defaultValue: 0);
    if(uploadFileTime>0) {
      DateTime lastTime = DateTool.getDateTimeFrom(DateTool.getSecondsFrom(uploadFileTime));
      DateTime nowTime = DateTime.now();
      if(DateTool.isSameDay(lastTime, nowTime)) {
        print('============  is same day  ============  ');
        return;
      }
    }

    String path = await getDatabasesPath();
    final dio = Dio();
    dio.options.headers.addAll({'token':read(NetConst.keyUserToken, global: true)});
    dio.options.contentType='application/octet-stream';
    dio.interceptors.add(LogInterceptor(requestBody: true, responseBody: true));

    // String dbPath = '$path/$dbName';
    String dbPath = '$path/$dbName';
    String md5sum = await AppUtil.getFileMd5(dbPath);
    String sha256sum = await AppUtil.getFilesha256(dbPath);
    String objectKey = 'watch/$userId/$sn/$fileName';
    Map<String, dynamic> params = {"md5sum":md5sum, "objectKey":objectKey, "sha256sum":sha256sum, "sn":sn};
    try {
      Response response = await dio.put(uploadSignURL, data: FormData.fromMap(params));
      Map map = jsonDecode(jsonEncode(response.data));
      if(map['code']==200) {
        _postFile(map);
      }
      return response;
    } catch(e){
      if(e is DioException) {
        return e.response;
      } else {
        return e.toString();
      }
    }
  }

  Future<dynamic> _postFile(Map map) async {
    String dbPath = await getDatabasesPath();
    Map dataMap = map['data'];
    Map<String, dynamic> headerVo = dataMap['headerVo'];
    String sha256 = headerVo['sha256'];
    String date = headerVo['date'];
    String authorization = headerVo['authorization'];
    String md5 = headerVo['md5'];
    String tagValue = headerVo['tagValue'];

    Map<String, dynamic> headers = {};
    if(authorization.isNotEmpty) {
      headers['Authoriration'] = authorization;
    }
    if(sha256.isNotEmpty) {
      headers['X-Amz-Content-Sha256'] = sha256;
    }
    if(date.isNotEmpty) {
      headers['X-Amz-Date'] = date;
    }
    if(md5.isNotEmpty) {
      headers['Content-Md5'] = md5;
    }
    // if(tagValue.isNotEmpty) {
    //   headers['x-???-tagging'] = tagValue;
    // }

    Map urlVo = dataMap['urlVo'];
    String scheme = urlVo['scheme'];
    String netloc = urlVo['netloc'];
    String path = urlVo['path'];
    String query = urlVo['query'];
    if(scheme.isEmpty||netloc.isEmpty||path.isEmpty) {
      return;
    }

    String postUrl = '$scheme://$netloc$path';
    if(query.isNotEmpty) {
      postUrl += '?$query';
    }
    Map<String, dynamic> body = {};
    body['file'] = await MultipartFile.fromFile('$dbPath/$dbName');

    final dio = Dio();
    dio.options.headers.addAll(headers);
    dio.options.contentType='application/octet-stream';
    dio.interceptors.add(LogInterceptor(requestBody: true, responseBody: true));
    try {
      Response response = await dio.put(postUrl, data: FormData.fromMap(body),
        onSendProgress: (progress, total) {
          print('onSendProgress progress:$progress/total:$total');
        },
      );
      Map map = jsonDecode(jsonEncode(response.data));
      if(map['code']==200) {
        save(keyUploadFileTime, DateTime.now().millisecondsSinceEpoch);
      }
      return response;
    } catch(e){
      if(e is DioException) {
        return e.response;
      } else {
        return e.toString();
      }
    }
  }

  Future<dynamic> deleteFile() async {
    String sn = read(UTEPedConst.keyAddress, global: true).replaceAll(':', '');
    String userId = read('login_id', global: true);
    final dio = Dio();
    dio.options.headers.addAll({'token':read(NetConst.keyUserToken, global: true)});
    dio.interceptors.add(LogInterceptor(requestBody: true, responseBody: true));

    String objectKey = 'watch/$userId/$sn/$fileName';
    Map<String, dynamic> params = {"objectKey":objectKey};

    try{
      Response response = await dio.delete('$deleteURL$sn', queryParameters: params);
      return response;
    } catch(e) {
      return e.toString();
    }
  }
}
